package com.xframe.domain.sys;

import com.xframe.domain.BaseModel;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.xframe.domain.emnus.PublicFieldEnum;
import com.xframe.xdal.core.annotation.*;
import com.xframe.xdal.core.autofill.IAutoFillBean;
import com.xframe.xdal.core.constant.AutoFillType;
import com.xframe.xdal.core.model.mapping.IColumnMapping;
import lombok.Data;
import lombok.experimental.Accessors;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 系统实体字段信息表
 *
 * @author xufeng
 * @version 1.0
 * @date 2023-03-28
 */
@Data
@Accessors(chain = true)
@XTable(value = "SYS_MODEL_ATTR", label = "模型字段表")
@XSelectItem(keyName = "attrId",codeName = "attrId",textName = "attrName")
@XBelongsTo(typeName = "com.xframe.domain.sys.SysModel",foreignKey = "modelId", targetKey = "modelId",as = "refSysModel")
@XHasMany(typeName = "com.xframe.domain.sys.SysModelAttrValProc",foreignKey = "attrId", targetKey = "attrId",as = "attrValProcList",refName = "refSysModelAttr")
public class SysModelAttr extends BaseModel implements Comparable<SysModelAttr>, IColumnMapping {

    /**
     * 字段处理器ID
     */
    @AutoFill(AutoFillType.Snowflake)
    @JsonSerialize(using = com.fasterxml.jackson.databind.ser.std.ToStringSerializer.class)
    @XColumn(name = "MODEL_ATTR_ID", primaryKeyFlag = true,desc = "字段处理器ID")
    private Long attrId;

    /**
     * 模型ID
     */
    @XColumn(name = "MODEL_ID",uniqueFlag = true,desc = "模型ID")
    @JsonSerialize(using = com.fasterxml.jackson.databind.ser.std.ToStringSerializer.class)
    private Long modelId;


    /**
     * 是否主键标记  Y = 是 N = 否
     */
    @AutoFill(defVal = "N")
    @XColumn(name = "PK_FLAG",desc = "是否主键",length = 1)
    private String pkFlag = "N";

    /**
     * 是否唯一键标记  Y = 是 N = 否
     */
    @AutoFill(defVal = "N")
    @XColumn(name = "AK_FLAG",desc = "是否唯一键",length = 1)
    private String akFlag = "N";

    /**
     * 唯一标识名(名字相同的是一组)
     */
    @AutoFill(defVal = "MAIN")
    @XColumn(name = "UNIQUE_NAME",desc = "唯一标识名",uniqueFlag = true,length = 50)
    private String uniqueName;
    /**
     * 字段编码 数据库名称
     */
    @XColumn(name = "MODEL_ATTR_CODE",uniqueFlag = true,desc = "字段编码",length = 50)
    private String code;

    /**
     * 字段描述 类属性名称
     */
    @XColumn(name = "MODEL_ATTR_NAME",desc = "类属性名称",length = 50)
    private String attrName;

    /**
     * 字段类型
     */
    @XColumn(name = "ATTR_TYPE",desc = "字段类型",length = 50)
    private String type;

    /**
     * 是否必填  Y = 是 N = 否
     */
    @AutoFill(defVal = "Y")
    @XColumn(name = "IS_REQUIRED",desc = "是否必填",length = 1)
    private String requiredFlag;

    /**
     * 字段描述
     */
    @XColumn(name = "ATTR_DESC",desc = "字段描述",length = 500)
    private String desc;

    /**
     * 字段长度
     */
    @XColumn(name = "ATTR_LEN",desc = "字段长度")
    private Integer len;

    /**
     * 字段精度
     */
    @AutoFill(defVal = "0")
    @XColumn(name = "SCALE",desc = "字段精度")
    private Integer sacle;

    /**
     * 字段排序
     */
    @AutoFill(defVal = "99")
    @XColumn(name = "SORT_NO",desc = "字段排序")
    private Integer sortNo;

    /**
     * 是否只读 Y = 是 N = 否
     */
    @AutoFill(defVal = "N")
    @XColumn(name = "IS_READONLY",desc = "是否只读",length = 1)
    private String readonlyFlag = "N";


    /**
     * 是否删除标记 Y = 是 N = 否
     */
    @AutoFill(defVal = "N")
    @XColumn(name = "IS_DEL_FLAG",desc = "是否删除标记",length = 1)
    private String delFlagValue = "N";


    /**
     * 是否版本号标记 Y = 是 N = 否
     */
    @AutoFill(defVal = "N")
    @XColumn(name = "IS_VER_FLAG",desc = "是否版本号标记",length = 1)
    private String verFlagValue = "N";


    /**
     * 是否使用数据库自动生成值 Y = 是 N = 否
     */
    @AutoFill(defVal = "N")
    @XColumn(name = "IS_USE_DB_FLAG",desc = "是否使用数据库表达式",length = 1)
    private String useDbFlag = "N";


    /**
     * 自动生成的表达式
     */
    //@AutoFill(defVal = "NONE")
    @XColumn(name = "DB_EXPRESS",desc = "数据库表达式",length = 200)
    private String dbExpress = "N";


    @AutoFill(defVal = "1")
    @XColumn(name = "BUILD_TYPE",desc = "字段创建类型")
    private Integer buildType ;



    @Override
    public int compareTo(SysModelAttr sysModelAttr) {

        return this.sortNo - sysModelAttr.sortNo;
    }

    /**
     * 引用的字段列表
     */
    @JsonIgnore
    private SysModel refSysModel;

    /**
     * 引用的字段处理器
     */
    private List<SysModelAttrValProc> attrValProcList;

    @Override
    public String getName() {
        return this.code;
    }

    @Override
    public String getFieldName() {
        return this.attrName;
    }

    @Override
    public boolean getPrimaryKeyFlag() {
        return this.pkFlag != null && this.pkFlag.equals("Y");
    }

    @Override
    public boolean getUniqueFlag() {
        return this.akFlag != null && this.akFlag.equals("Y");
    }

    @Override
    public boolean getUseDbObjectFlag() {
        return this.useDbFlag != null && this.useDbFlag.equals("Y");
    }

    @Override
    public String getDbExpression() {
        return this.dbExpress;
    }

    @Override
    public Class<?> getDataType() {
//        if(StringUtil.isEmpty(this.type)){
//            this.type = String.class.getName();
//        } else {
//            this.type = getAttrType(this.type.toUpperCase());
//        }

        try {
            return Class.forName(this.type);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            return String.class;
        }
    }

    @Override
    public Integer getLength() {
        return this.len;
    }

    @Override
    public boolean getDeleteFlag() {
        return this.delFlagValue != null && this.delFlagValue.equals("Y");
    }
    /**
     * 是否是空
     *
     * @return true 是 false 否
     */
    @Override
    public boolean getNullFlag() {
        return this.requiredFlag == null || this.requiredFlag.equals("N");
    }

    @Override
    public boolean getDbGeneratedFlag() {
        return false;
    }

    @Override
    public boolean getVersionFlag() {
        return this.verFlagValue != null && this.verFlagValue.equals("Y");
    }

    @Override
    public boolean getReadonly() {
        return this.readonlyFlag != null && this.readonlyFlag.equals("Y");
    }

    @Override
    public String getAkGroupName() {
        return "";
    }

    @Override
    public Integer getScale() {
        return this.sacle;
    }

    @Override
    public List<IAutoFillBean> getAutoFillBeanList() {
        if(this.attrValProcList == null){
            return null;
        }
        return new ArrayList<>(this.attrValProcList);
    }




    public static List<SysModelAttr> findNoPublicAttr(List<SysModelAttr> modelAttrList){
        List<SysModelAttr> noPublicItemList = new ArrayList<>();
        if(modelAttrList == null){
            return noPublicItemList;
        }

        for(SysModelAttr modelAttr : modelAttrList){
            if(PublicFieldEnum.isPublicFieldNoDelFlag(modelAttr.getAttrName())){
                continue;
            }
            noPublicItemList.add(modelAttr);
        }
        return noPublicItemList;
    }

    public static List<SysModelAttr> findNoPublicAttrAndPK(List<SysModelAttr> modelAttrList){
        List<SysModelAttr> noPublicItemList = new ArrayList<>();
        if(modelAttrList == null){
            return noPublicItemList;
        }

        for(SysModelAttr modelAttr : modelAttrList){
            if(modelAttr.pkFlag.equals("Y") || PublicFieldEnum.isPublicFieldNoDelFlag(modelAttr.getAttrName())){
                continue;
            }
            noPublicItemList.add(modelAttr);
        }
        return noPublicItemList;
    }

    public static List<SysModelAttr> findFromAttr(List<SysModelAttr> modelAttrList){
        List<SysModelAttr> fromAttrItemList = new ArrayList<>();
        if(modelAttrList == null){
            return fromAttrItemList;
        }

        for(SysModelAttr modelAttr : modelAttrList){
            if(PublicFieldEnum.isFormField(modelAttr.getAttrName())){
                continue;
            }
            fromAttrItemList.add(modelAttr);
        }
        return fromAttrItemList;
    }



    /**
     * 将字段类型转换为 class字符串
     * @param type
     * @return
     */
    public static String getAttrType(String type){
        AttrType attrType = AttrType.getByCode(type.toUpperCase());
        switch (attrType) {
            case LONG:
                return "java.lang.Long";
            case TIME:
                return "java.sql.Time";
            case BOOLEAN:
                return "java.lang.Boolean";
            case FLOAT:
                return "java.lang.Float";
            case DECIMAL:
                return "java.math.BigDecimal";
            case INTEGER:
                return "java.lang.Integer";
            case STRING:
                return "java.lang.String";
            case DATE:
                return "java.util.Date";
            case DOUBLE:
                return "java.lang.Double";
        }
        return "java.lang.String";
    }

}
